/**
 * 
 */
package soa.security.mgr.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.naming.Name;

import org.apache.commons.lang3.StringUtils;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import soa.security.Constants;
import soa.security.domain.OrganizationUnit;
import soa.security.domain.Person;
import soa.security.domain.Role;
import soa.security.domain.Role.Roles;
import soa.security.exception.AdapterException;
import soa.security.exception.OrganizationException;
import soa.security.mgr.service.RoleMgrService;
import soa.security.util.BeanUtils;
import soa.security.util.JaxbUtils;

/**
 * @author Cre.Gu
 *
 */
@Service
public class RoleMgrServiceImpl extends BaseMgrServiceImpl implements
		RoleMgrService {
	protected final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(this.getClass());

	@Override
	public void addRole(String organizationId, Role bean)
			throws OrganizationException {
		try {
			validate(bean);
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.ROLE);

			bean.setDn(bean.buildDn(unit.getDn()));
			roleDao.create(bean);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	@Override
	public void updateRole(String organizationId, Role bean)
			throws OrganizationException {
		try {
			validate(bean);
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(unit.getDn().toString(), bean.getBid());

			bean.setDn(bean.buildDn(unit.getDn()));
			roleDao.update(bean);
		} catch (Exception e) {
			wrapException(e);
		}
	}

	private void validate(Role d) {
		Assert.hasText(d.getBid(), "角色编码不能为空");
		Assert.hasText(d.getName(), "角色名称不能为空");

		BeanUtils.blank2Null(d);
	}

	@Override
	public List<Role> allRoles(String organizationId)
			throws OrganizationException {
		try {
			validateOrganization(organizationId);

			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			return roleDao
					.allRoles(unit.getDn().toString(), defaultSearchScope);
		} catch (Exception e) {
			wrapException(e);
		}
		return null;
	}

	@Override
	public List<Role> getRole(String organizationId, String roleId)
			throws OrganizationException {
		List<Role> list = new ArrayList<Role>();
		try {
			validateOrganization(organizationId);
			OrganizationUnit unit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(unit.getDn().toString(), roleId);

			Name dn = LdapNameBuilder.newInstance(unit.getDn())
					.add(Constants.BID, roleId).build();
			list.add(roleDao.findByDn(dn.toString()));

		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public boolean addPersons(String organizationId, String roleId,
			String personIds) throws OrganizationException {
		try {
			validateOrganization(organizationId);

			OrganizationUnit poUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(poUnit.getDn().toString(), roleId);

			Role role = roleDao.findByPrimaryKey(poUnit.getDn().toString(),
					roleId);

			String[] pids = StringUtils.split(personIds, ",");
			for (String pid : pids) {
				OrganizationUnit unit = gainOrganizationUnit(organizationId,
						Constants.PERSON);

				validatePerson(unit.getDn().toString(), pid);
				roleDao.addPersons(role, personDao.findByPrimaryKey(unit
						.getDn().toString(), pid));

			}

			return true;
		} catch (Exception e) {
			wrapException(e);
		}
		return false;
	}

	@Override
	public boolean removePersons(String organizationId, String roleId,
			String personIds) throws OrganizationException {
		try {
			validateOrganization(organizationId);

			OrganizationUnit poUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(poUnit.getDn().toString(), roleId);

			Role role = roleDao.findByPrimaryKey(poUnit.getDn().toString(),
					roleId);

			String[] pids = StringUtils.split(personIds, ",");
			for (String pid : pids) {
				OrganizationUnit unit = gainOrganizationUnit(organizationId,
						Constants.PERSON);

				validatePerson(unit.getDn().toString(), pid);
				roleDao.removePersons(role, personDao.findByPrimaryKey(unit
						.getDn().toString(), pid));

			}

			return true;
		} catch (Exception e) {
			wrapException(e);
		}
		return false;
	}

	@Override
	public List<Person> allPersons(String organizationId, String roleId)
			throws OrganizationException {
		List<Person> list = new ArrayList<Person>();
		try {
			if (StringUtils.isBlank(roleId))
				return list;

			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(deUnit.getDn().toString(), roleId);

			List<String> pids = roleDao.allPersons(roleDao.findByPrimaryKey(
					deUnit.getDn().toString(), roleId));

			for (String string : pids) {
				list.add(personDao.findByDn(string));
			}
		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public boolean addSubRoles(String organizationId, String roleId,
			String subRoleIds) throws OrganizationException {
		try {

			validateOrganization(organizationId);

			OrganizationUnit poUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(poUnit.getDn().toString(), roleId);

			Role role = roleDao.findByPrimaryKey(poUnit.getDn().toString(),
					roleId);

			String[] pids = StringUtils.split(subRoleIds, ",");
			for (String pid : pids) {
				OrganizationUnit unit = gainOrganizationUnit(organizationId,
						Constants.ROLE);

				validateRole(unit.getDn().toString(), pid);
				roleDao.addSubRoles(role,
						roleDao.findByPrimaryKey(unit.getDn().toString(), pid));

			}

			return true;
		} catch (Exception e) {
			wrapException(e);
		}
		return false;
	}

	@Override
	public boolean removeSubRoles(String organizationId, String roleId,
			String subRoleIds) throws OrganizationException {
		try {
			validateOrganization(organizationId);

			OrganizationUnit poUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(poUnit.getDn().toString(), roleId);

			Role role = roleDao.findByPrimaryKey(poUnit.getDn().toString(),
					roleId);

			String[] pids = StringUtils.split(subRoleIds, ",");
			for (String pid : pids) {
				OrganizationUnit unit = gainOrganizationUnit(organizationId,
						Constants.ROLE);

				validateRole(unit.getDn().toString(), pid);
				roleDao.removeSubRoles(role,
						roleDao.findByPrimaryKey(unit.getDn().toString(), pid));

			}

			return true;
		} catch (Exception e) {
			wrapException(e);
		}
		return false;
	}

	@Override
	public List<Role> allSubRoles(String organizationId, String roleId)
			throws OrganizationException {
		List<Role> list = new ArrayList<Role>();
		try {
			if (StringUtils.isBlank(roleId))
				return list;

			validateOrganization(organizationId);
			OrganizationUnit deUnit = gainOrganizationUnit(organizationId,
					Constants.ROLE);
			validateRole(deUnit.getDn().toString(), roleId);

			List<String> pids = roleDao.allSubRoles(roleDao.findByPrimaryKey(
					deUnit.getDn().toString(), roleId));

			for (String string : pids) {
				list.add(roleDao.findByDn(string));
			}
		} catch (Exception e) {
			wrapException(e);
		}
		return list;
	}

	@Override
	public List<Role> adapt(String xml) throws AdapterException {
		try {
			Roles bs = JaxbUtils.xml2Object(xml, Roles.class);
			return bs.getRole();

		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}
	}

	@Override
	public String unadapt(List<Role> list) throws AdapterException {
		try {
			Roles bs = new Roles();
			bs.addAll(list);

			return JaxbUtils.object2Xml(bs, Roles.class);
		} catch (Exception e) {
			if (log.isDebugEnabled())
				log.debug("格式转换错误", e);
			throw new AdapterException(AdapterException.ERROR_01);
		}
	}

	@Override
	public Role findByDn(String dn) throws OrganizationException {
		try {
			return roleDao.findByDn(dn);

		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return null;
		}
	}

	@Override
	public boolean deleteByDn(String dn) throws OrganizationException {
		try {
			roleDao.deleteByDn(dn);
			return true;
		} catch (Exception e) {
			printException(e);
			if (log.isDebugEnabled())
				log.debug("错误信息", e);

			return false;
		}
	}

	@Override
	public boolean removeAllSubRoles(String organizationId, String roleId)
			throws OrganizationException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void addOrRemove(String organizationId, String roleId,
			String personIds) {
		// 原来的personIds
		List<String> origs = allPersonIds(allPersons(organizationId, roleId));
		// form 提交的personIds
		List<String> forms = formIds(personIds);

		// 要增加的personIds
		List<String> adds = addIds(origs, forms);
		// 要删除的personIds
		List<String> rems = removeIds(origs, forms);

		addPersons(organizationId, roleId, StringUtils.join(adds, ","));
		removePersons(organizationId, roleId, StringUtils.join(rems, ","));

	}

	@Override
	public void addOrRemoveSub(String organizationId, String roleId,
			String subRoleIds) {
		// 原来的personIds
		List<String> origs = allSubIds(allSubRoles(organizationId, roleId));
		// form 提交的personIds
		List<String> forms = formIds(subRoleIds);

		// 要增加的personIds
		List<String> adds = addIds(origs, forms);
		// 要删除的personIds
		List<String> rems = removeIds(origs, forms);

		addSubRoles(organizationId, roleId, StringUtils.join(adds, ","));
		removeSubRoles(organizationId, roleId, StringUtils.join(rems, ","));

	}

	private List<String> allSubIds(List<Role> list) {
		List<String> origs = new ArrayList<String>();
		for (Role gr : list) {
			origs.add(gr.getBid());
		}
		return origs;
	}
}
